package com.px.project.module.it.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles;
import com.px.common.dto.BaseQueryDto;
import com.px.common.dto.BiNumDto;
import com.px.common.dto.FileInfoQueryDto;
import com.px.common.entity.SysUser;
import com.px.common.service.FileInfoService;
import com.px.common.service.IFileManageService;
import com.px.common.service.SysUserService;
import com.px.common.util.AssertUtil;
import com.px.common.util.EntityUtil;
import com.px.common.util.PoiUtil;
import com.px.project.module.it.constant.FileTypeConstant;
import com.px.project.module.it.dto.ProblemRectifyQueryDto;
import com.px.project.module.it.entity.ProblemRectify;
import com.px.project.module.it.enums.CheckReportExceptionEnum;
import com.px.project.module.it.mapper.ProblemRectifyMapper;
import com.px.project.module.it.service.IProblemRectifyService;
import com.px.project.module.it.vo.ProblemRectifyVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 问题整改 服务实现类
 *
 * @author 品讯科技
 * @since 2023-11-03
 */
@Service
@RequiredArgsConstructor
public class ProblemRectifyServiceImpl extends ServiceImpl<ProblemRectifyMapper, ProblemRectify> implements IProblemRectifyService {

    private final SysUserService sysUserService;

    private final FileInfoService fileInfoService;

    private final IFileManageService fileManageService;

    @Override
    public ProblemRectifyVo getById(Long id) {
        Set<Long> userIds = new HashSet<>();
        ProblemRectifyVo vo = baseMapper.getProblemRectifyVoById(id);
        List<Long> baseLeaders = new ArrayList<>();
        Map<Long,String> userMap = sysUserService.list(Wrappers.lambdaQuery(SysUser.class)
                        .in(SysUser::getId,userIds).select(SysUser::getId,SysUser::getName))
                .stream().collect(Collectors.toMap(SysUser::getId,SysUser::getName));
        if (vo.getBaseLeader()!=null){
            baseLeaders = Arrays.stream(vo.getBaseLeader().split(StrUtil.COMMA)).map(Long::valueOf).collect(Collectors.toList());
            userIds.addAll(baseLeaders);
            vo.setBaseLeaderName(baseLeaders.stream().map(userMap::get).collect(Collectors.joining(StrUtil.COMMA)));
        }
        List<Long> checkPersons = new ArrayList<>();
        if (vo.getCheckPerson()!=null){
            checkPersons = Arrays.stream(vo.getCheckPerson().split(StrUtil.COMMA)).map(Long::valueOf).collect(Collectors.toList());
            userIds.addAll(checkPersons);
            vo.setCheckPersonName(checkPersons.stream().map(userMap::get).collect(Collectors.joining(StrUtil.COMMA)));
        }
        FileInfoQueryDto fileInfoQueryDto = new FileInfoQueryDto();
        fileInfoQueryDto.setType(FileTypeConstant.PROBLEM_RECTIFY_ANNEX);
        fileInfoQueryDto.setBiId(id);
        vo.setAnnexList(fileInfoService.getFileInfo(fileInfoQueryDto));

        return vo;
    }

    @Override
    public Page<ProblemRectifyVo> page(BaseQueryDto<ProblemRectifyVo> pageDto, ProblemRectifyQueryDto queryDto) {
        Page<ProblemRectifyVo> page = pageDto.toPage();

        int total = baseMapper.getProblemRectifyVoTotal(queryDto);
        List<ProblemRectifyVo> list;
        long pages;
        if(total > 0){
            pages = (long) Math.ceil((double) total / page.getSize());
            //Page对象会被mybatis直接解析分页参数
            list = baseMapper.getProblemRectifyVo(pageDto,queryDto,FileTypeConstant.PROBLEM_RECTIFY_ANNEX);
            //回写人员名称
            String baseLeaderStr = list.stream().map(ProblemRectify::getBaseLeader).collect(Collectors.joining(StrUtil.COMMA));
            List<Long> baseLeaders = Arrays.stream(baseLeaderStr.split(StrUtil.COMMA)).map(Long::valueOf).collect(Collectors.toList());

            String checkPersonStr = list.stream().map(ProblemRectify::getCheckPerson).collect(Collectors.joining(StrUtil.COMMA));
            List<Long> checkPersons = Arrays.stream(checkPersonStr.split(StrUtil.COMMA)).map(Long::valueOf).collect(Collectors.toList());

            Set<Long> userIds = new HashSet<>();
            userIds.addAll(baseLeaders);
            userIds.addAll(checkPersons);
            Map<Long,String> userMap = sysUserService.list(Wrappers.lambdaQuery(SysUser.class)
                            .in(SysUser::getId,userIds).select(SysUser::getId,SysUser::getName))
                    .stream().collect(Collectors.toMap(SysUser::getId,SysUser::getName));

            list.forEach(vo -> {
                vo.setBaseLeaderName(Arrays.stream(vo.getBaseLeader().split(StrUtil.COMMA))
                        .map(userId -> userMap.get(Long.valueOf(userId))).collect(Collectors.joining(StrUtil.COMMA)));
                vo.setCheckPersonName(Arrays.stream(vo.getCheckPerson().split(StrUtil.COMMA))
                        .map(userId -> userMap.get(Long.valueOf(userId))).collect(Collectors.joining(StrUtil.COMMA)));
            });
        }else{
            list = new ArrayList<>();
            pages = 0L;
        }
        page.setTotal(total);
        page.setRecords(list);
        page.setPages(pages);

        return page;
    }

    @Override
    @Transactional
    public Long saveProblemRectify(ProblemRectify rectify) throws Exception {
        BiNumDto numDto = EntityUtil.getMaxBiNumDto(baseMapper);

        rectify.setNum(numDto.getNum());
        rectify.setCommandNum(numDto.getNumStr());

        super.save(rectify);
        //生成验收报告
        generatorCheckReport(rectify.getId());

        return rectify.getId();
    }

    @Override
    @Transactional
    public boolean updateProblemRectify(ProblemRectify rectify) throws Exception {
        //generatorCheckReport会重新查询
        super.updateById(rectify);
        //生成验收报告
        return generatorCheckReport(rectify.getId());
    }

    @Override
    public String getCommandNum() {
        return EntityUtil.getMaxBiNumDto(baseMapper).getNumStr();
    }

    @Override
    public boolean generatorCheckReport(Long id) throws Exception {
        ProblemRectifyVo vo = this.getById(id);

        AssertUtil.isNotNull(vo, CheckReportExceptionEnum.CHECK_REPORT_EXISTS,id);

        XWPFDocument document = new XWPFDocument(new ClassPathResource(FileTypeConstant.PROBLEM_RECTIFY_TEMPLATE).getStream());
        //设置追加内容的默认字体大小
        CTStyles ctStyles = document.getStyle();
        //normalSize = size / 2
        ctStyles.getStyleArray(0).getRPr().getSz().setVal(BigInteger.valueOf(22));
        //段落操作
        List<XWPFParagraph> paragraphList = document.getParagraphs();
        for (XWPFParagraph paragraph : paragraphList) {
            String text = paragraph.getText();
            if (text.contains("projectShortName")) {
                PoiUtil.replaceParagraphText(paragraph, "projectShortName", vo.getProjectShortName());
            }
            String numberStr = EntityUtil.getMaxBiNumDto(baseMapper).getNumStr();
            if (text.contains("numberStr")) {
                PoiUtil.replaceParagraphText(paragraph, "numberStr", numberStr);
            }
        }
        //表格操作,表格样式过于难调整，表格不新增表格，利用先设置好的样式表格进行操作
        String fontFamily0 = "仿宋";
        List<XWPFTable> tableList = document.getTables();
        //验收主信息
        XWPFTable mainTable = tableList.get(0);

        PoiUtil.getXWPFRun(mainTable.getRow(0).getCell(1),true,fontFamily0,12)
                .setText(vo.getBaseCheck());

        PoiUtil.getXWPFRun(mainTable.getRow(0).getCell(3),true,fontFamily0,12)
                .setText(vo.getBaseLeaderName());

        PoiUtil.getXWPFRun(mainTable.getRow(1).getCell(1),true,fontFamily0,12)
                .setText(vo.getCheckBranch());

        PoiUtil.getXWPFRun(mainTable.getRow(1).getCell(3),true,fontFamily0,12)
                .setText(DateUtil.formatChineseDate(vo.getReceiveDate(),false,false));

        PoiUtil.getXWPFRun(mainTable.getRow(2).getCell(0),false,fontFamily0,null)
                .setText(vo.getRemark());
        //字符可能有换行符
        PoiUtil.addBreakInCell(mainTable.getRow(2).getCell(0));

        PoiUtil.getXWPFRun(mainTable.getRow(3).getCell(0),false,fontFamily0,null)
                .setText(vo.getRectifyOpinion());
        //字符可能有换行符
        PoiUtil.addBreakInCell(mainTable.getRow(3).getCell(0));

        PoiUtil.getXWPFRun(mainTable.getRow(4).getCell(0),false,fontFamily0,null)
                .setText(vo.getPunishOpinion());
        //字符可能有换行符
        PoiUtil.addBreakInCell(mainTable.getRow(4).getCell(0));

        PoiUtil.getXWPFRun(mainTable.getRow(5).getCell(1),fontFamily0)
                .setText(vo.getLeaderOpinion());

        PoiUtil.getXWPFRun(mainTable.getRow(5).getCell(3),fontFamily0)
                .setText(DateUtil.formatChineseDate(vo.getSendDate(),false,false));

        PoiUtil.getXWPFRun(mainTable.getRow(6).getCell(1),false,fontFamily0,null)
                .setText(vo.getCheckPersonName());

        //先删除之前生成的报告
        if(StrUtil.isNotBlank(vo.getReportPath())){
            fileManageService.deleteFileByPath(vo.getReportPath());
        }
        vo.setReportPath(fileManageService.uploadWord(FileTypeConstant.PROBLEM_RECTIFY_REPORT,document));

        return super.updateById(vo);
    }

}
